package ar.frba.utn.diseñosistemas.TP2;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.Queue;

import org.uqbar.commons.model.UserException;

public class Asiento 
{
	private String codigoVuelo;
	private String numeroAsiento;
	private float precio;
	private Clase clase;
	private Ubicacion ubicacion;
	private EstadoAsiento estado;
	private String fechaSalida;
	private String horaSalida;
	private String fechaLlegada;
	private String horaLlegada;
	private String destino;
	private String origen;
	
	private Aerolinea aerolinea;
	private Queue<Reserva> reservas; //La primera es la reserva registrada en la aerolinea, el resto son sobre-reservas
	
	public Asiento(String codigoVuelo, String numeroAsiento, float precio
				 , Clase clase, Ubicacion ubicacion, EstadoAsiento estado
				 , String fechaSalida, String horaSalida
				 , String fechaLlegada, String horaLlegada
				 , Aerolinea aerolinea, String origen, String destino) 
	{
		this.setCodigoVuelo(codigoVuelo);
		this.setNumeroAsiento(numeroAsiento);
		this.setPrecio(precio);
		this.setClase(clase);
		this.setUbicacion(ubicacion);
		this.setEstado(estado);
		this.setAerolinea(aerolinea);
		this.setFechaSalida(fechaSalida);
		this.setHoraSalida(horaSalida);
		this.setFechaLlegada(fechaLlegada);
		this.setHoraLlegada(horaLlegada);
		this.setOrigen(origen);
		this.setDestino(destino);
		
		this.reservas = new LinkedList<Reserva>();
	}
	
	public void comprar(Usuario unUsuario) 
	{
		try
		{
			if (!puedeComprarEsteAsiento(unUsuario))
				throw new UserException("Este asiento fue reservado por otra persona");
				
			this.getAerolinea().comprar(this, unUsuario);
			
			eliminarReservas();
			AterrizarSingleton.getInstance().incrementarPopularidad(this.getCodigoVuelo());
		}
		catch (Exception e) {
			throw new UserException(e.getMessage());
		}
	}

	private void eliminarReservas() 
	{
		for (Reserva reserva : reservas) 
			reserva.sacarAsiento(this);
		
		reservas.clear();
	}

	public void reservarEnAerolinea(Usuario unUsuario)
	{
		this.aerolinea.reservar(this, unUsuario);
	}

	public void agregarReserva(Reserva unaReserva)
	{
		this.reservas.add(unaReserva);
	}
	
	public String getCodigoVuelo() {
		return codigoVuelo;
	}
	public void setCodigoVuelo(String codigo) {
		this.codigoVuelo = codigo;
	}
	
	public String getNumeroAsiento()
	{
		return this.numeroAsiento;
	}
	public void setNumeroAsiento(String numeroAsiento)
	{
		this.numeroAsiento = numeroAsiento;
	}
	
	public String getDestino()
	{
		return this.destino;
	}
	public void setDestino(String destino)
	{
		this.destino = destino;
	}
	
	public String getOrigen()
	{
		return this.origen;
	}
	public void setOrigen(String origen)
	{
		this.origen = origen;
	}
	
	public float getPrecio() {
		return precio;
	}
	public void setPrecio(float precio) {
		this.precio = precio;
	}
	
	public Clase getClase() {
		return this.clase;
	}
	public void setClase(Clase clase) {
		this.clase = clase;
	}
	
	public Ubicacion getUbicacion() {
		return ubicacion;
	}
	public void setUbicacion(Ubicacion ubicacion) {
		this.ubicacion = ubicacion;
	}
	
	public EstadoAsiento getEstado() {
		return estado;
	}
	public void setEstado(EstadoAsiento estado) {
		this.estado = estado;
	}

	public void setAerolinea(Aerolinea aerolinea) {
		this.aerolinea = aerolinea;
	}
	public Aerolinea getAerolinea() {
		return aerolinea;
	}
	
	public void setFechaSalida(String fechaSalida) {
		this.fechaSalida = fechaSalida;
	}

	public String getFechaSalida() {
		return fechaSalida;
	}

	public void setHoraSalida(String horaSalida) {
		this.horaSalida = horaSalida;
	}

	public String getHoraSalida() {
		return horaSalida;
	}

	public void setFechaLlegada(String fechaLlegada) {
		this.fechaLlegada = fechaLlegada;
	}

	public String getFechaLlegada() {
		return fechaLlegada;
	}

	public void setHoraLlegada(String horaLlegada) {
		this.horaLlegada = horaLlegada;
	}

	public String getHoraLlegada() {
		return horaLlegada;
	}

	public boolean esSuperOferta() {
	
		return (this.clase == Clase.Primera && this.precio < 8000) 
			|| (this.clase == Clase.Ejecutivo && this.precio < 4000);
	}

	private Boolean puedeComprarEsteAsiento(Usuario unUsuario) 
	{
		if (!this.reservas.isEmpty())
		{
			Reserva unaReserva = this.reservas.peek();
			
			return unaReserva.perteneceA(unUsuario);
		}
		
		return true;
	}

	public boolean estaReservado() 
	{
		return this.aerolinea.estaReservado(this);
	}

	public void transferirReserva()
	{
		Reserva reserva = this.reservas.poll();
		reserva.sacarAsiento(this);
		
		if (this.reservas.isEmpty()){
			this.setEstado(EstadoAsiento.Disponible);
			this.aerolinea.cambiarEstadoAsientoADisponible(this);
		}
		else
		{
			//this.setEstado(EstadoAsiento.Disponible);
			this.aerolinea.cambiarEstadoAsientoADisponible(this);
			Reserva siguienteReserva = this.reservas.peek();
			this.reservarEnAerolinea(siguienteReserva.getUsuario());
		}
	}

	public long getTiempoDeVuelo() 
	{
		try
		{
			SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm");
			Date salida = format.parse(fechaSalida + " " + horaSalida);
			Date llegada = format.parse(fechaLlegada + " " + horaLlegada);
			
			return Math.abs(salida.getTime() - llegada.getTime());
		}
		catch(Exception ex)
		{
			throw new UserException("No se pudo calcular el tiempo de vuelo");
		}
	}

	public String getNombreAerolinea()
	{
		return this.aerolinea.getNombre();
	}
	
	public Asiento clonar()
	{
		return new Asiento(getCodigoVuelo(), getNumeroAsiento(), 
						   getPrecio(), getClase(), 
						   getUbicacion(), getEstado(),
						   getFechaSalida(), getHoraSalida(),
						   getFechaLlegada(), getHoraLlegada(),
						   getAerolinea(), getOrigen(), getDestino());
	}

	
	public int getPopularidadVuelo() 
	{
		return AterrizarSingleton.getInstance().getPopularidadDe(this.getCodigoVuelo());
	}

	public Queue<Reserva> getReservas() {
		
		return this.reservas;
	}
}
